﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QueueUnlimited.API;
using System.Configuration;
using MultiplayerDice.Implementation.Command;

namespace MultiplayerDice.Implementation
{
    public static class Bootstrapper
    {
        private static List<MessageListener> listeners = new List<MessageListener>();

        public static void OnStartUp()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["MultiplayerDiceEventBusConnectionString"].ConnectionString;
            // Configure subscribers:
            using (var dataStore = new DataStore(connectionString))
            {
                // Query_LastUsers:
                var lastUsersSubscriber = new Subscriber("QuerySubscriber_LastUsers");
                lastUsersSubscriber.AddEvent(typeof(BusinessEvent.NewPlayerRegisteredEvent).FullName);
                // Query_Choose opponent:
                var chooseOpponentSubscriber = new Subscriber("QuerySubscriber_ChooseOpponent");
                chooseOpponentSubscriber.AddEvent(typeof(BusinessEvent.NewPlayerRegisteredEvent).FullName);
                // Query_Open Games:
                var openGamesSubscriber = new Subscriber("QuerySubscriber_OpenGames");
                openGamesSubscriber.AddEvents(
                    typeof(BusinessEvent.NewGameStartedEvent).FullName,
                    typeof(BusinessEvent.ExistingGameEndedEvent).FullName);
                // Query_Ended games
                var endedGamesSubscriber = new Subscriber("QuerySubscriber_EndedGames");
                endedGamesSubscriber.AddEvent(typeof(BusinessEvent.ExistingGameEndedEvent).FullName);

                // Command game processor:
                var gameCommandProcessorSubscriber = new Subscriber("CommandSubscriber_Games");
                gameCommandProcessorSubscriber.AddEvents(
                    typeof(NewGameStartedCommand).FullName,
                    typeof(ExistingGameEndedCommand).FullName);

                // Saving the configuration:
                dataStore.Configuration.Apply(chooseOpponentSubscriber);
                dataStore.Configuration.Apply(lastUsersSubscriber);
                dataStore.Configuration.Apply(openGamesSubscriber);
                dataStore.Configuration.Apply(endedGamesSubscriber);
                dataStore.Configuration.Apply(gameCommandProcessorSubscriber);

                // Listeners:
                // Commands:
                listeners.Add(new MessageListener(Processor.GameCommandsProcessor.Process, connectionString, gameCommandProcessorSubscriber));
                // Queries:
                listeners.Add(new MessageListener(Processor.LastUserProcessor.Process, connectionString, lastUsersSubscriber));
                listeners.Add(new MessageListener(Processor.ChooseOpponentProcessor.Process, connectionString, chooseOpponentSubscriber));
                listeners.Add(new MessageListener(Processor.OpenGamesProcessor.Process, connectionString, openGamesSubscriber));
                listeners.Add(new MessageListener(Processor.EndedGamesProcessor.Process, connectionString, endedGamesSubscriber));
            }

            listeners.ForEach((l) => l.OnMessageProcessingFault += (sender, args) => Infrastructure.Logging.Log(args.Exception, args.CurrentMessage));
        }

        public static void OnShutdown()
        {
            listeners.ForEach((l) => l.Dispose());
        }
    }
}
